package sketch.specs;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

import sketch.util.Checker;

/**
 * Note that it finds the value declaration used in the given block! not defined in
 * the given block!
 * */
public class SpecValueDeclarationFinder {

	public final Block block;
	
	public final Block parentblock;
	
	public final int blockStartPos;
	
	public SpecValueDeclarationFinder(Block block) {
		Checker.checkNull(block, "The block could not be null!");
		this.block = block;
		//System.out.println(block);
		Checker.checkNull(block.getParent(), "The parent of the current block " + block + "can not be null!");
		//in the next method, the variable declaration is fetched from its parent block!
		Checker.checkTrue(block.getParent() instanceof Block , //|| (block.getParent() instanceof MethodDeclaration),
				"The parent of current block is not block type , " +
				"it is type: " + this.block.getParent().getClass());
		this.parentblock = (block.getParent() instanceof Block) ? (Block)block.getParent() :
			    ((MethodDeclaration)block.getParent()).getBody();
		this.blockStartPos = block.getStartPosition();
	}
	
	public List<VariableDeclarationStatement> getAllValueDeclaredStatements() {
		List<VariableDeclarationStatement> retstmts = new LinkedList<VariableDeclarationStatement>();
		//return;
		List<Statement> statements = this.parentblock.statements();
		for(Statement statement : statements) {
			if(statement.getStartPosition() >= this.blockStartPos) {
				break;
			}
			if(statement instanceof VariableDeclarationStatement) {
				if(isValuesStatement((VariableDeclarationStatement)statement)) {
					retstmts.add((VariableDeclarationStatement)statement);
				}
			}
		}
		return retstmts;
	}
	
	public static List<VariableDeclarationStatement> findVariableDeclarationStatements(Block block) {
		Checker.checkNull(block, "The block input could not be null!");
		List<VariableDeclarationStatement> retstmts = new LinkedList<VariableDeclarationStatement>();
		//return;
		List<Statement> statements = block.statements();
		for(Statement statement : statements) {
			if(statement instanceof VariableDeclarationStatement) {
				if(isValuesStatement((VariableDeclarationStatement)statement)) {
					retstmts.add((VariableDeclarationStatement)statement);
				}
			}
		}
		return retstmts;
	}
	
	public static boolean isValuesStatement(VariableDeclarationStatement statement) {
//		String str = statement.toString();
//		return (str.indexOf("Values.choose(")!= - 1) || (str.indexOf("Values.chooseArray(") != -1)
//		    || (str.indexOf("Values.randomChoose(") != -1) || (str.indexOf("Values.exhaust(") != -1);
		return SpecValueDeclarationRemover.isSpecValueDeclarationStatement(statement);
	}
	
	public static boolean isChooseValeuStatement(VariableDeclarationStatement statement) {
		return SpecValueDeclarationRemover.isSpecValueDeclarationStatement(statement, new String[]{"Values", "sketch.ounit.Values"}, new String[]{"choose"});
	}
}